import { put, takeEvery, takeLatest } from 'redux-saga/effects'

import { changeLngLat, safeJsonParse } from '@/utils/util'
import call from '../call'
import { PATROLCENTER } from '../actionTypes'
import {
  updateCityInfo,
  updateAreaInfo,
  updateKeyAreaInfo,
  updateParkingAreaInfo,
  updateSearchKeyAreaInfo,
  updateSearchParkingAreaInfo,
  updateSearchBufferParkingAreaInfo,
} from '../reducers/patrolCenter'
import {
  queryCityInfo as queryCityInfoService,
  queryKeyAreaInfo as queryKeyAreaInfoService,
  queryAreaRegion as queryAreaRegionService,
  queryParkingAreaInfo as queryParkingAreaInfoService,
  querySearchParkingArea as querySearchParkingAreaService,
} from '../service/patrolCenter'

function* queryCityInfo(action: Action) {
  const res: ResponseData = yield call(queryCityInfoService, action)
  if (res?.code === 0 && res.data) {
    yield put(updateCityInfo(res.data))
  }
}

function* queryKeyAreaInfo(action: Action) {
  const res: ResponseData = yield call(queryKeyAreaInfoService, action)
  if (res.code === 0 && res.data) {
    const keyAreaInfo = res.data || []
    const coordinates = keyAreaInfo.map((position: any) => {
      const region = safeJsonParse(position['fencingGeoJson'])
      return {
        ...position,
        rawRegion: region,
        region: changeLngLat(region.coordinates),
      }
    })
    if (action.payload?.searchString) {
      yield put(updateSearchKeyAreaInfo(coordinates))
      yield action.cb?.(coordinates)
    } else {
      yield put(updateKeyAreaInfo(coordinates))
    }
  }
}

function* queryAreaRegion(action: Action) {
  const res: ResponseData = yield call(queryAreaRegionService, action)
  if (res?.code === 0 && res.data) {
    const { center = [], region = {} } = res.data
    const areaInfo = { region: changeLngLat(region.coordinates), center }
    yield put(updateAreaInfo(areaInfo))
  }
}

function* queryParkingAreaInfo(action: Action) {
  const res: ResponseData = yield call(queryParkingAreaInfoService, action)
  if (res?.code === 0 && res.data) {
    const parkingLocationInfo = res.data.parkingLocationInfo || []
    const coordinates = parkingLocationInfo.map((position: any) => {
      const region = safeJsonParse(position['region'])
      return {
        ...position,
        rawRegion: region,
        region: changeLngLat(region.coordinates),
      }
    })
    yield put(updateParkingAreaInfo(coordinates))
  }
}

function* querySearchParkingArea(action: Action) {
  const res: ResponseData = yield call(querySearchParkingAreaService, action)
  if (res?.code === 0 && res.data) {
    const { parkingArea } = action.extra || {}
    const parkingLocationInfo = res.data || []
    const searchBufferCoordinates: any = []
    const coordinates = [parkingLocationInfo].map((position: any) => {
      if (position.depositBufferGeoJson) {
        const region = safeJsonParse(position['depositBufferGeoJson'])
        searchBufferCoordinates.push({
          ...position,
          region: changeLngLat(region.coordinates),
        })
      }
      const region = safeJsonParse(position['region'])
      return {
        ...position,
        rawRegion: region,
        isEdit: parkingArea?.fencingId === position.fencingId,
        isSearched: true,
        region: changeLngLat(region.coordinates),
      }
    })
    if (parkingLocationInfo && action.cb) {
      action.cb(parkingLocationInfo)
    }
    yield put(updateSearchParkingAreaInfo(coordinates))
    yield put(updateSearchBufferParkingAreaInfo(searchBufferCoordinates))
  } else if (res?.code === 0 && !res.data) {
    action.cb?.(res.data)
  }
}

export default function* root() {
  yield takeLatest(PATROLCENTER.QUERY_CITY_INFO, queryCityInfo)
  yield takeLatest(PATROLCENTER.QUERY_AREA_REGION, queryAreaRegion)
  yield takeEvery(PATROLCENTER.QUERY_KEY_AREA_INFO, queryKeyAreaInfo)
  yield takeLatest(PATROLCENTER.QUERY_PARKING_AREA_INFO, queryParkingAreaInfo)
  yield takeLatest(PATROLCENTER.QUERY_SEARCH_PARKING_AREA, querySearchParkingArea)
}
